//
//  RayCastCallback.h
//  CutCut
//
//  Created by Bullet Hermit on 12-11-2.
//  Copyright (c) 2012年 紫竹飞燕. All rights reserved.
//

#ifndef CutCut_RayCastCallback_h
#define CutCut_RayCastCallback_h
#import "Box2D.h"
#import "PolygonSprite.h"
#define collinear(x1,y1,x2,y2,x3,y3)  ((y2-y1)*(x3-x1)-(y3-y1)*(x2-x1))
class RayCastCallback : public b2RayCastCallback
{
public:
    RayCastCallback(){}
    float32 ReportFixture(b2Fixture *fixture,const b2Vec2 &point,const b2Vec2 &normal,float32 fraction)
    {
        PolygonSprite* ps = (PolygonSprite*) fixture->GetBody()->GetUserData();
        if (!ps.isSliceEntered) {
            ps.isSliceEntered =YES;
            ps.entryPoint = ps.body->GetLocalPoint(point);
            
            ps.sliceEntryTime = CACurrentMediaTime()+1;

        } else if(!ps.isSliceExited){
            ps.exitPoint = ps.body->GetLocalPoint(point);
            //ps.isSliceExited = YES;
            //determine whether they are on the same side by the centroid
            b2Vec2 entrySide = ps.entryPoint-ps.centroid;
            b2Vec2 exitSide = ps.exitPoint - ps.centroid;
            if(entrySide.x*exitSide.x<0||entrySide.y*exitSide.y<0)
            {
                ps.isSliceExited = YES;
            }
            else{
            //determine whether they are on the same side of the polygon 
                b2PolygonShape* shape = (b2PolygonShape*)ps.body->GetFixtureList()->GetShape();
                int count = shape->GetVertexCount();
                BOOL onSameLine = NO;
                for(int i=0;i!=count;++i)
                {
                    b2Vec2 pointA = shape->GetVertex(i);
                    b2Vec2 pointB;
                    if(i!=count-1)
                    {
                        pointB = shape->GetVertex(i+1);
                    }
                    else
                    {
                        pointB = shape->GetVertex(0);
                    }
                    float collinear = collinear(pointA.x, pointA.y , pointB.x , pointB.y , ps.entryPoint.x , ps.entryPoint.y );
                    if(collinear<0.00001)
                    {
                        float collinear2 = collinear(pointA.x, pointA.y , pointB.x , pointB.y , ps.exitPoint.x , ps.exitPoint.y );
                        if(collinear2<0.00001)
                        {
                            onSameLine = YES;
                            break;
                        }
                    }
                }
                if(onSameLine)
                {
                    ps.entryPoint = ps.exitPoint;
                    ps.sliceEntryTime = CACurrentMediaTime()+1;
                    ps.isSliceExited=NO;
                }
                else
                    ps.isSliceExited = YES;
            }

        }
        return 1;
    }
};

#endif
